package com.ck.company.service.impl;

import com.ck.common.service.OperationLogService;
import com.ck.company.service.CpProgramPutinService;
import com.ck.constant.*;
import com.ck.dao.*;
import com.ck.exception.ServiceException;
import com.ck.model.common.*;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 节目投放
 * <p>
 * 1.同一时段可以有多个节目下发，终端下载的节目按照节目优先级排队，优先级相同的节目，按照下载下来时间排序
 * 2.插播计划节目优先级最高，同一时间段，同一台机器只能下发一个插播计划
 * 3.普1：开始时间无限制，结束时间有限制；普2：开始时间有限制、结束时间有限制；普3：开始时间有限制、结束时间无限制，
 * 普4：开始时间无限制，结束时间无限制）
 * 4.节目优先级排序（插播>普1>普2>普3>普4）
 *
 * @author linqiang
 * @date 2018-06-20 18:30
 */
@Service(value = "cpProgramPutinService")
public class CpProgramPutinServiceImpl implements CpProgramPutinService {

    @Autowired
    private ProgramPutinMapper programPutinMapper;
    @Autowired
    private DeviceProgramMapper deviceProgramMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private ProgramMapper programMapper;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private DeviceGroupMapper deviceGroupMapper;

    /**
     * 新增节目投放设置（选择mac）
     *
     * @param programId       节目ID
     * @param putinLevel      投放级别（1普通计划，2插播计划）
     * @param putinStartTime  投放开始时间
     * @param putinEndTime    投放结束时间
     * @param putinDeviceMacs 投放终端mac(多个英文逗号隔开)
     * @param request         请求
     * @return 投放设置成功返回true, 反之false
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ProgramPutin putinByDeviceMac(Long programId, Integer putinLevel, Long putinStartTime, Long putinEndTime,
                                         String putinDeviceMacs, HttpServletRequest request) {
        Program p = programMapper.selectByPrimaryKey(programId);
        if (null == p) {
            return null;
        }
        if (StringUtils.isNotBlank(putinDeviceMacs)) {
            if (null == putinStartTime) {
                putinStartTime = ProgramPutinConstant.UNLIMIT_START_TIME;
            }
            if (null == putinEndTime) {
                putinEndTime = ProgramPutinConstant.UNLIMIT_END_TIME;
            }
            String[] deviceMacArr = putinDeviceMacs.split(",");
            if (deviceMacArr.length > 0) {
                batchInsertDeviceProgram(p.getProgramVersion(), Arrays.asList(deviceMacArr), putinStartTime, putinEndTime);
                ProgramPutin programPutin = new ProgramPutin();
                programPutin.setProgramVersion(p.getProgramVersion());
                programPutin.setPutinDeviceMacs(putinDeviceMacs);
                programPutin.setPutinStartTime(putinStartTime);
                programPutin.setPutinEndTime(putinEndTime);
                programPutin.setAddTime(System.currentTimeMillis());
                programPutin.setPutinLevel(putinLevel);
                programPutinMapper.insertAndReturnId(programPutin);

                //更新节目信息
                Integer commonLevel = this.getCommonLevelByPutinTime(putinLevel, putinStartTime, putinEndTime);
                p.setPutinLevel(putinLevel);
                p.setCommonLevel(commonLevel);
                p.setDownloadDeviceSum(deviceMacArr.length);
                p.setAddStatus(ProgramConstant.ADD_STATUS_APPROVAL_PUBLISH);
                p.setUpdateTime(System.currentTimeMillis());
                p.setOverdueTime(putinEndTime);
                programMapper.updateByPrimaryKey(p);
                operationLogService.saveSuccessOperationLog("新增节目投放设置成功，节目ID为："
                        + p.getProgramId() + "，节目名称为：" + p.getProgramName() + "，投放的终端mac为："
                        + putinDeviceMacs, ModuleConstant.MODULE_PROGRAM, request);
                return programPutin;
            }
        }
        return null;
    }

    /**
     * 新增节目投放设置（选择mac）
     *
     * @param programId        节目ID
     * @param putinLevel       投放级别（1普通计划，2插播计划）
     * @param putinStartTime   投放开始时间
     * @param putinEndTime     投放结束时间
     * @param putinDeviceCodes 投放终端code(多个英文逗号隔开)
     * @param request          请求
     * @return 投放设置成功返回true, 反之false
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ProgramPutin putinByDeviceCode(Long programId, Integer putinLevel, Long putinStartTime, Long putinEndTime,
                                          String putinDeviceCodes, HttpServletRequest request) {
        Program p = programMapper.selectByPrimaryKey(programId);
        if (null == p) {
            return null;
        }
        if (StringUtils.isNotBlank(putinDeviceCodes)) {
            if (null == putinStartTime) {
                putinStartTime = ProgramPutinConstant.UNLIMIT_START_TIME;
            }
            if (null == putinEndTime) {
                putinEndTime = ProgramPutinConstant.UNLIMIT_END_TIME;
            }
            String[] deviceCodeArr = putinDeviceCodes.split(",");
            if (deviceCodeArr.length > 0) {
                batchInsertDeviceProgram(p.getProgramVersion(), Arrays.asList(deviceCodeArr), putinStartTime, putinEndTime);
                ProgramPutin programPutin = new ProgramPutin();
                programPutin.setProgramVersion(p.getProgramVersion());
                programPutin.setPutinDeviceCodes(putinDeviceCodes);
                programPutin.setPutinStartTime(putinStartTime);
                programPutin.setPutinEndTime(putinEndTime);
                programPutin.setAddTime(System.currentTimeMillis());
                programPutin.setPutinLevel(putinLevel);
                programPutinMapper.insertAndReturnId(programPutin);

                //更新节目信息
                Integer commonLevel = this.getCommonLevelByPutinTime(putinLevel, putinStartTime, putinEndTime);
                p.setPutinLevel(putinLevel);
                p.setCommonLevel(commonLevel);
                p.setDownloadDeviceSum(deviceCodeArr.length);
                p.setAddStatus(ProgramConstant.ADD_STATUS_APPROVAL_PUBLISH);
                p.setUpdateTime(System.currentTimeMillis());
                p.setOverdueTime(putinEndTime);
                programMapper.updateByPrimaryKey(p);
                operationLogService.saveSuccessOperationLog("新增节目投放设置成功，节目ID为："
                        + p.getProgramId() + "，节目名称为：" + p.getProgramName() + "，投放的终端CODE为："
                        + putinDeviceCodes, ModuleConstant.MODULE_PROGRAM, request);
                return programPutin;
            }
        }
        return null;
    }

    /**
     * 新增节目投放设置（选择终端组）
     *
     * @param programId            节目ID
     * @param putinLevel           投放级别（1普通计划，2插播计划）
     * @param putinStartTime       投放开始时间
     * @param putinEndTime         投放结束时间
     * @param putinDeviceGroupId   投放终端组ID(多个英文逗号隔开)
     * @param putinDeviceGroupName 投放终端组名称(多个英文逗号隔开)
     * @param request              请求
     * @return 投放设置成功返回true, 反之false
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ProgramPutin putinByDeviceGroup(Long programId, Integer putinLevel, Long putinStartTime, Long putinEndTime, String putinDeviceGroupId,
                                           String putinDeviceGroupName, HttpServletRequest request) throws ServiceException {
        Program p = programMapper.selectByPrimaryKey(programId);
        if (null == p) {
            return null;
        }
        User user = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        if (null == user) {
            throw new ServiceException(UserConstant.USER_NOT_LOGIN);
        }
        if (StringUtils.isNotBlank(putinDeviceGroupId)) {
            if (null == putinStartTime) {
                putinStartTime = ProgramPutinConstant.UNLIMIT_START_TIME;
            }
            if (null == putinEndTime) {
                putinEndTime = ProgramPutinConstant.UNLIMIT_END_TIME;
            }
            long now = System.currentTimeMillis();
            List<String> deviceCodeList = this.selectDeviceCodeListByDeviceGroupIds(putinDeviceGroupId, user.getCompanyCode());
            if (CollectionUtils.isNotEmpty(deviceCodeList)) {
                this.batchInsertDeviceProgram(p.getProgramVersion(), deviceCodeList, putinStartTime, putinEndTime);
                p.setDownloadDeviceSum(deviceCodeList.size());
            } else {
                throw new ServiceException(ProgramPutinConstant.MSG_PUTIN_NO_DEVICE);
            }
            boolean isNew = false;
            ProgramPutin programPutin = programPutinMapper.selectByProgramVersion(p.getProgramVersion());
            if (null == programPutin) {
                programPutin = new ProgramPutin();
                isNew = true;
            }
            programPutin.setProgramVersion(p.getProgramVersion());
            if (putinDeviceGroupId.contains(String.valueOf(DeviceGroupConstant.ALL_DEVICE_GROUP_ID))) {
                putinDeviceGroupId = String.valueOf(DeviceGroupConstant.ALL_DEVICE_GROUP_ID);
            }
            programPutin.setPutinDeviceGroup(putinDeviceGroupId);
            programPutin.setPutinStartTime(putinStartTime);
            programPutin.setPutinEndTime(putinEndTime);
            programPutin.setAddTime(now);
            programPutin.setPutinLevel(putinLevel);
            if (isNew) {
                programPutinMapper.insertAndReturnId(programPutin);
            } else {
                programPutinMapper.updateByPrimaryKey(programPutin);
            }

            //更新节目信息
            Integer commonLevel = this.getCommonLevelByPutinTime(putinLevel, putinStartTime, putinEndTime);
            p.setPutinLevel(putinLevel);
            p.setCommonLevel(commonLevel);
            p.setAddStatus(ProgramConstant.ADD_STATUS_APPROVAL_PUBLISH);
            p.setUpdateTime(now);
            p.setOverdueTime(programPutin.getPutinEndTime());
            programMapper.updateByPrimaryKey(p);
            String content = "新增节目投放设置成功，节目ID为：" + p.getProgramId() + "，节目名称为：" + p.getProgramName();
            String groupNames = getDeviceGroupName(putinDeviceGroupId, user.getCompanyCode());
            if (StringUtils.isNotBlank(groupNames)) {
                content += "，投放的终端组为：" + groupNames;
            }
            operationLogService.saveSuccessOperationLog(content, ModuleConstant.MODULE_PROGRAM, request);
            return programPutin;
        }
        return null;
    }

    /**
     * 更新节目投放设置（选择终端组）
     *
     * @param programPutinId       节目投放ID
     * @param putinLevel           投放级别（1普通计划，2插播计划）
     * @param startTimeL           投放开始时间
     * @param endTimeL             投放结束时间
     * @param putinDeviceGroupId   投放终端组ID(多个英文逗号隔开)
     * @param putinDeviceGroupName 投放终端组名称(多个英文逗号隔开)
     * @param request
     * @return 影响行数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updatePutinByDeviceGroup(Long programPutinId, Integer putinLevel, Long startTimeL, Long endTimeL,
                                        String putinDeviceGroupId, String putinDeviceGroupName, HttpServletRequest request)
            throws ServiceException {
        ProgramPutin programPutin = programPutinMapper.selectByPrimaryKey(programPutinId);
        if (null == programPutin) {
            return 0;
        }
        Program p = programMapper.selectByProgramVersion(programPutin.getProgramVersion());
        if (null == p) {
            return 0;
        }
        User user = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        if (null == user) {
            throw new ServiceException(UserConstant.USER_NOT_LOGIN);
        }
        int row = 0;
        if (StringUtils.isNotBlank(putinDeviceGroupId)) {
            if (null == startTimeL) {
                startTimeL = ProgramPutinConstant.UNLIMIT_START_TIME;
            }
            if (null == endTimeL) {
                endTimeL = ProgramPutinConstant.UNLIMIT_END_TIME;
            }

            long now = System.currentTimeMillis();
            List<String> deviceCodeList = this.selectDeviceCodeListByDeviceGroupIds(putinDeviceGroupId, user.getCompanyCode());
            if (CollectionUtils.isNotEmpty(deviceCodeList)) {
                this.batchInsertDeviceProgram(p.getProgramVersion(), deviceCodeList, startTimeL, endTimeL);
                p.setDownloadDeviceSum(deviceCodeList.size());
            } else {
                throw new ServiceException(ProgramPutinConstant.MSG_PUTIN_NO_DEVICE);
            }
            programPutin.setPutinDeviceCodes(null);
            programPutin.setPutinDeviceGroup(putinDeviceGroupId);
            programPutin.setPutinStartTime(startTimeL);
            programPutin.setPutinEndTime(endTimeL);
            programPutin.setUpdateTime(now);
            programPutin.setPutinLevel(putinLevel);
            row = programPutinMapper.updateByPrimaryKey(programPutin);

            //更新节目信息
            Integer commonLevel = this.getCommonLevelByPutinTime(putinLevel, startTimeL, endTimeL);
            p.setPutinLevel(putinLevel);
            p.setCommonLevel(commonLevel);
            p.setUpdateTime(now);
            p.setOverdueTime(programPutin.getPutinEndTime());
            p.setAddStatus(ProgramConstant.ADD_STATUS_APPROVAL_PUBLISH);
            programMapper.updateByPrimaryKey(p);
            String content = "更新节目投放设置成功，节目ID为：" + p.getProgramId() + "，节目名称为：" + p.getProgramName();
            if (StringUtils.isNotBlank(putinDeviceGroupName)) {
                content += "，投放的终端组为：" + putinDeviceGroupName;
            }
            String groupNames = getDeviceGroupName(putinDeviceGroupId, user.getCompanyCode());
            if (StringUtils.isNotBlank(groupNames)) {
                content += "，投放的终端组为：" + groupNames;
            }
            operationLogService.saveSuccessOperationLog(content, ModuleConstant.MODULE_PROGRAM, request);
        }
        return row;
    }

    /**
     * 更新节目投放设置（选择mac）
     *
     * @param programPutinId   节目投放ID
     * @param putinLevel       投放级别（1普通计划，2插播计划）
     * @param startTimeL       投放开始时间
     * @param endTimeL         投放结束时间
     * @param putinDeviceCodes 投放终端code(多个英文逗号隔开)
     * @param request          请求
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int updatePutinByDeviceCode(Long programPutinId, Integer putinLevel, Long startTimeL, Long endTimeL,
                                       String putinDeviceCodes, HttpServletRequest request) throws ServiceException {
        User user = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        if (null == user) {
            throw new ServiceException(UserConstant.USER_NOT_LOGIN);
        }
        ProgramPutin programPutin = programPutinMapper.selectByPrimaryKey(programPutinId);
        if (null == programPutin) {
            return 0;
        }
        Program program = programMapper.selectByProgramVersion(programPutin.getProgramVersion());
        if (null == program) {
            return 0;
        }
        int row = 0;
        if (StringUtils.isNotBlank(putinDeviceCodes)) {
            if (null == startTimeL) {
                startTimeL = ProgramPutinConstant.UNLIMIT_START_TIME;
            }
            if (null == endTimeL) {
                endTimeL = ProgramPutinConstant.UNLIMIT_END_TIME;
            }
            String[] deviceCodeArr = putinDeviceCodes.split(",");
            if (deviceCodeArr.length > 0) {
                this.batchInsertDeviceProgram(programPutin.getProgramVersion(), Arrays.asList(deviceCodeArr), startTimeL, endTimeL);
                programPutin.setPutinDeviceCodes(putinDeviceCodes);
                programPutin.setPutinStartTime(startTimeL);
                programPutin.setPutinEndTime(endTimeL);
                programPutin.setPutinDeviceGroup(null);
                programPutin.setUpdateTime(System.currentTimeMillis());
                programPutin.setPutinLevel(putinLevel);
                row = programPutinMapper.updateByPrimaryKey(programPutin);

                //更新节目信息
                Integer commonLevel = this.getCommonLevelByPutinTime(putinLevel, startTimeL, endTimeL);
                program.setPutinLevel(putinLevel);
                program.setCommonLevel(commonLevel);
                program.setDownloadDeviceSum(deviceCodeArr.length);
                program.setUpdateTime(System.currentTimeMillis());
                program.setOverdueTime(programPutin.getPutinEndTime());
                program.setAddStatus(ProgramConstant.ADD_STATUS_APPROVAL_PUBLISH);
                programMapper.updateByPrimaryKey(program);
                operationLogService.saveSuccessOperationLog("更新节目投放设置成功，节目ID为："
                        + program.getProgramId() + "，节目名称为：" + program.getProgramName() + "，投放的终端CODE为："
                        + putinDeviceCodes, ModuleConstant.MODULE_PROGRAM, request);
            }
        }
        return row;
    }

    /**
     * 批量插入终端节目关联
     *
     * @param programVersion 节目版本号
     * @param deviceCodeList 终端code集合
     * @param putinStartTime 投放开始时间
     * @param putinEndTime   投放结束时间
     */
    private void batchInsertDeviceProgram(String programVersion, List<String> deviceCodeList, Long putinStartTime, Long putinEndTime) {
        if (CollectionUtils.isNotEmpty(deviceCodeList) && StringUtils.isNotBlank(programVersion)) {
            long dateNow = System.currentTimeMillis();
            //删除已有的节目终端关联
            deviceProgramMapper.deleteByProgramVersion(programVersion, dateNow);
            //添加新的节目终端关联
            List<DeviceProgram> deviceProgramList = new ArrayList<>();
            DeviceProgram deviceProgram = null;
            for (String code : deviceCodeList) {
                if (StringUtils.isNotBlank(code)) {
                    deviceProgram = new DeviceProgram();
                    deviceProgram.setPutinStartTime(putinStartTime);
                    deviceProgram.setPutinEndTime(putinEndTime);
                    deviceProgram.setDeviceCode(code.trim());
                    deviceProgram.setProgramVersion(programVersion);
                    deviceProgram.setAddTime(dateNow);
                    deviceProgram.setUpdateTime(dateNow);
                    deviceProgram.setDataStatus(ProgramPutinConstant.DATA_STATUS_EFFECTIVE);
                    deviceProgramList.add(deviceProgram);
                }
            }
            if (CollectionUtils.isNotEmpty(deviceProgramList)) {
                deviceProgramMapper.batchInsert(deviceProgramList);
            }
        }
    }

    /**
     * 根据终端分组ID查询终端code
     *
     * @param putinDeviceGroupId 终端分组ID（多个英文逗号隔开）
     * @param companyCode        商家编号
     * @return mac集合
     */
    private List<String> selectDeviceCodeListByDeviceGroupIds(String putinDeviceGroupId, String companyCode) {
        List<String> deviceCodeList = new ArrayList<>();
        String[] groupIdArr = putinDeviceGroupId.split(",");
        if (groupIdArr.length == 0) {
            return deviceCodeList;
        }
        List<String> groupIdList = new ArrayList<>(Arrays.asList(groupIdArr));
        //未分组
        if (groupIdList.contains(String.valueOf(DeviceGroupConstant.NO_DEVICE_GROUP_ID))) {
            List<String> noGroupCodeList = deviceMapper.selectDeviceCodesNoGroup(companyCode);
            groupIdList.remove(String.valueOf(DeviceGroupConstant.NO_DEVICE_GROUP_ID));
            deviceCodeList.addAll(noGroupCodeList);
        }

        //全部分组
        if (groupIdList.contains(String.valueOf(DeviceGroupConstant.ALL_DEVICE_GROUP_ID))
                || putinDeviceGroupId.contains(String.valueOf(DeviceGroupConstant.ALL_DEVICE_GROUP_ID))) {
            List<String> allGroupCodeList = deviceMapper.selectDeviceCodesByDeviceGroupsWithGroup(null, companyCode);
            deviceCodeList.addAll(allGroupCodeList);
            return deviceCodeList;
        }

        //指定分组
        if (groupIdList.size() > 0) {
            List<String> specifyGroupCodeList = deviceMapper.selectDeviceCodesByDeviceGroupsWithGroup(groupIdList, companyCode);
            deviceCodeList.addAll(specifyGroupCodeList);
        }
        return deviceCodeList;
    }

    /**
     * 根据节目投放时间获取节目级别
     * 插播:0 > 普1:1 > 普2:2 > 普3:3 > 普4:4
     *
     * @param putinLevel 投放级别（1普通，2插播）
     * @param startTime  投放开始时间
     * @param endTime    投放结束时间
     * @return 普通节目级别
     */
    private Integer getCommonLevelByPutinTime(Integer putinLevel, Long startTime, Long endTime) {
        if (ProgramPutinConstant.LEVEL_INSERTING == putinLevel) {
            return ProgramPutinLevelEnum.INSERTING.getType();
        } else {
            if (ProgramPutinConstant.UNLIMIT_START_TIME.equals(startTime) && !ProgramPutinConstant.UNLIMIT_END_TIME.equals(endTime)) {
                return ProgramPutinLevelEnum.COMMON_1.getType();
            }
            if (!ProgramPutinConstant.UNLIMIT_START_TIME.equals(startTime) && !ProgramPutinConstant.UNLIMIT_END_TIME.equals(endTime)) {
                return ProgramPutinLevelEnum.COMMON_2.getType();
            }
            if (!ProgramPutinConstant.UNLIMIT_START_TIME.equals(startTime) && ProgramPutinConstant.UNLIMIT_END_TIME.equals(endTime)) {
                return ProgramPutinLevelEnum.COMMON_3.getType();
            }
            if (ProgramPutinConstant.UNLIMIT_START_TIME.equals(startTime) && ProgramPutinConstant.UNLIMIT_END_TIME.equals(endTime)) {
                return ProgramPutinLevelEnum.COMMON_4.getType();
            }
        }
        return null;
    }

    /**
     * 根据终端组ID和商家编码查询终端组名称（多个以英文逗号隔开）
     *
     * @param putinDeviceGroupId 终端组ID(多个英文逗号隔开)
     * @param companyCode        商家编码
     * @return 终端组名称
     */
    private String getDeviceGroupName(String putinDeviceGroupId, String companyCode) {
        String groupNames = "";
        if (putinDeviceGroupId.contains(DeviceGroupConstant.ALL_DEVICE_GROUP_CODE)) {
            //全部分组
            groupNames = "全部分组";
        } else {
            List<String> strings = Arrays.asList(putinDeviceGroupId.split(","));
            if (strings.size() > 0) {
                groupNames = programPutinMapper.selectDeviceGroupNameByDeviceGroupCode(strings, companyCode);
            }
        }
        return groupNames;
    }
}
